package com.link2room.soundwave.facade.impl;

import com.link2room.common.constant.BaseConstant;
import com.link2room.common.constant.DefaultValue;
import com.link2room.common.enums.BaseSysExceptionEnum;
import com.link2room.common.jpa.condition.ConditionDetail;
import com.link2room.common.jpa.condition.L2RCondition;
import com.link2room.common.jpa.criteria.CriteriaUtil;
import com.link2room.common.jpa.result.QueryResult;
import com.link2room.common.mns.MNSUtil;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.ClassConverUtil;
import com.link2room.common.util.JacksonUtil;
import com.link2room.common.util.L2RAssert;

import com.link2room.jetfire.constant.JetfireMnsConstant;
import com.link2room.jetfire.constant.ReservationConstant;
import com.link2room.jetfire.dto.param.base.ReservationParamDto;
import com.link2room.jetfire.dto.param.inside.ReservationNmsStaInsideParamDto;
import com.link2room.jetfire.dto.param.inside.ReservationPayInsideParamDto;

import com.link2room.jetfire.dto.result.base.ReservationBaseDto;
import com.link2room.soundwave.dto.param.api.MemeberCardPayApiParamDto;
import com.link2room.soundwave.dto.param.base.PmsReservationBaseParamDto;
import com.link2room.soundwave.dto.param.inside.BookInfoListInsideParamDto;
import com.link2room.soundwave.dto.param.inside.MemeberCardPayInsideParamDto;
import com.link2room.soundwave.dto.param.inside.PmsReservationPayInsideParamDto;
import com.link2room.soundwave.dto.param.inside.ReservationStaInsideParamDto;
import com.link2room.soundwave.dto.result.base.AccountResultDto;
import com.link2room.soundwave.dto.result.base.MemberCardPayDto;
import com.link2room.soundwave.dto.result.base.PmsAccountDto;
import com.link2room.soundwave.dto.result.base.PmsBookInfoDto;
import com.link2room.soundwave.entity.L2RIpms2Reservation;
import com.link2room.soundwave.exception.SoundwaveException;
import com.link2room.soundwave.facade.IPmsReservationHandlerFacadeService;
import com.link2room.soundwave.feign.jetfire.ReservationsFeignService;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;

/**
 * Created by VegetaKo on 2016/9/23.
 */
public abstract class AbstractReservationHandlerFacadeServiceImpl implements IPmsReservationHandlerFacadeService {
    @Resource
    private ICommonService commonService;
    @Resource
    private ReservationsFeignService reservationsFeignService;
    @Resource
    private MNSUtil mnsUtil;

    abstract void savePMSReservation(ReservationParamDto reservationParamDto) throws Exception;

    abstract void cancelPMSReservation(ReservationParamDto reservationParamDto) throws Exception;

    abstract void savePMSReservationPay(PmsReservationPayInsideParamDto pmsReservationPayInsideParamDto) throws Exception;

    abstract void syncReservationSta(ReservationStaInsideParamDto reservationStaInsideParamDto) throws Exception;

    abstract void syncPMSHotelReservationSta(PmsReservationBaseParamDto pmsReservationBaseParamDto) throws Exception;

    abstract QueryResult<PmsAccountDto> listPmsAccounts(PmsReservationBaseParamDto pmsReservationBaseParamDto)throws Exception;

    abstract AccountResultDto getAccountResult(PmsReservationBaseParamDto pmsReservationBaseParamDto)throws Exception;

    abstract String memberCardPrepay(MemeberCardPayInsideParamDto memeberCardPayInsideParamDto) throws Exception;

    abstract MemberCardPayDto memberCardPay(MemeberCardPayApiParamDto memeberCardPayApiParamDto) throws Exception;

    @Override
    public void savePMSReservationHandler(ReservationParamDto reservationParamDto) throws Exception {
        ReservationBaseDto reservationBaseDto=reservationParamDto.getReservationBase();
        if(reservationBaseDto==null){
            throw new SoundwaveException(BaseSysExceptionEnum.PARAM_IS_NULL,reservationParamDto.toString());
        }
        ReservationNmsStaInsideParamDto reservationNmsStaParam = new ReservationNmsStaInsideParamDto();
        reservationNmsStaParam.setOptId(reservationParamDto.getOptId());
        reservationNmsStaParam.setLhotelGroupCode(reservationBaseDto.getLhotelGroupCode());
        reservationNmsStaParam.setLhotelCode(reservationBaseDto.getLhotelCode());
        reservationNmsStaParam.setL2RNo(reservationBaseDto.getL2RNo());
        reservationNmsStaParam.setOperType(reservationParamDto.getOperType());
        reservationNmsStaParam.setItem(BaseConstant.ServiceCategoryConstant.SOUNDWAVE);
        try {
            savePMSReservation(reservationParamDto);

            reservationNmsStaParam.setOperSta(DefaultValue.T);
            mnsUtil.putMessageToQueue(JetfireMnsConstant.QUEUE_ORDER_STA, JacksonUtil.beanToJson(reservationNmsStaParam));
        }
        catch (Exception e){
            reservationNmsStaParam.setOperSta(DefaultValue.F);
            mnsUtil.putMessageToQueue(JetfireMnsConstant.QUEUE_ORDER_STA, JacksonUtil.beanToJson(reservationNmsStaParam));
            throw  e;
        }
    }

    @Override
    public void cancelPMSReservationHandler(ReservationParamDto reservationParamDto) throws Exception {
        cancelPMSReservation(reservationParamDto);
    }

    @Override
    public void savePMSReservationPayHandler(PmsReservationPayInsideParamDto pmsReservationPayInsideParamDto) throws Exception {
        savePMSReservationPay(pmsReservationPayInsideParamDto);
    }

    @Override
    public void syncReservationStaHandler(ReservationStaInsideParamDto reservationStaInsideParamDto) throws Exception {
        syncReservationSta(reservationStaInsideParamDto);
    }

    @Override
    public void syncPMSHotelReservationStaHandler(PmsReservationBaseParamDto pmsReservationBaseParamDto) throws Exception {
        syncPMSHotelReservationSta(pmsReservationBaseParamDto);
    }



    @Override
    public QueryResult<PmsBookInfoDto> getPMSReservationsHandler(BookInfoListInsideParamDto bookInfoListInsideParamDto) throws Exception {
        if( null!= bookInfoListInsideParamDto&& bookInfoListInsideParamDto.getL2rNos().length()>0){
            L2RCondition l2RCondition = new L2RCondition();
            List<String> l2rNoList= Arrays.asList(bookInfoListInsideParamDto.getL2rNos().split(","));

            ArrayList<ConditionDetail> conditionDetailArrayList = new ArrayList<>();
            conditionDetailArrayList.add(new ConditionDetail(L2RIpms2Reservation.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ,bookInfoListInsideParamDto.getLhotelGroupCode()));
            conditionDetailArrayList.add(new ConditionDetail(L2RIpms2Reservation.L2RIpms2Reservation_.l2RNo.toString(),CriteriaUtil.Operator.IN,l2rNoList));
            ConditionDetail[] conditionDetails = new ConditionDetail[conditionDetailArrayList.size()];
            for ( int i=0;i<conditionDetailArrayList.size();i++){
                conditionDetails[i]= conditionDetailArrayList.get(i);
            }
            l2RCondition.setAndConditions( conditionDetails);
            //l2RCondition.
            QueryResult<L2RIpms2Reservation> l2RIpms2ReservationQueryResult = commonService.findAllByCondition( L2RIpms2Reservation.class,l2RCondition);

            QueryResult<PmsBookInfoDto> pmsBookInfoDtoQueryResult= ClassConverUtil.copyQueryResultToDtoQueryResult(l2RIpms2ReservationQueryResult, PmsBookInfoDto.class, false);

            return pmsBookInfoDtoQueryResult;
        }
        else{
            return null;
        }
    }

    @Override
    public QueryResult<PmsAccountDto> listPmsAccountsHandler(PmsReservationBaseParamDto pmsReservationBaseParamDto)throws Exception{
        return listPmsAccounts(pmsReservationBaseParamDto);
    }

    @Override
    public AccountResultDto getAccountResultHandler(PmsReservationBaseParamDto pmsReservationBaseParamDto)throws Exception{
        return getAccountResult(pmsReservationBaseParamDto);
    }

    /**
     * 储值卡支付预下单
     *
     * @param memeberCardPayInsideParamDto
     */
    @Override
    public String memberCardPrepayHandler(MemeberCardPayInsideParamDto memeberCardPayInsideParamDto) throws Exception {
        String lhotelGroupCode=memeberCardPayInsideParamDto.getLhotelGroupCode();
        String lhotelCode=memeberCardPayInsideParamDto.getLhotelCode();
        String outerOrderNo=memeberCardPayInsideParamDto.getOrderNo();
        String memberNo=memeberCardPayInsideParamDto.getMemberNo();
        String taCode=memeberCardPayInsideParamDto.getTaCode();
        BigDecimal totalFee=memeberCardPayInsideParamDto.getTotalFee();
        L2RAssert.stringBlank(lhotelGroupCode,"lhotelGroupCode is null");
        L2RAssert.stringBlank(lhotelCode,"lhotelCode is null");
        L2RAssert.stringBlank(outerOrderNo,"outerOrderNo is null");
        L2RAssert.stringBlank(memberNo,"memberNo is null");
        L2RAssert.stringBlank(taCode,"taCode is null");
        L2RAssert.objectNull(totalFee,"totalFee is null");
        return memberCardPrepay(memeberCardPayInsideParamDto);
    }

    /**
     * 储值卡支付
     *
     * @param memeberCardPayApiParamDto
     */
    @Override

    public void memberCardPayHandler(MemeberCardPayApiParamDto memeberCardPayApiParamDto) throws Exception {
        String lhotelGroupCode=memeberCardPayApiParamDto.getLhotelGroupCode();
        String lhotelCode=memeberCardPayApiParamDto.getLhotelCode();
        String l2rNo=memeberCardPayApiParamDto.getL2RNo();
        String prepayId=memeberCardPayApiParamDto.getL2rPrepayId();
        String password=memeberCardPayApiParamDto.getPassword();
        //解码
        Base64.Decoder decoder = Base64.getDecoder();
        L2RAssert.stringBlank(lhotelGroupCode,"lhotelGroupCode is null");
        L2RAssert.stringBlank(prepayId,"prepayId is null");
        L2RAssert.stringBlank(password,"password is null");
        L2RAssert.stringBlank(lhotelCode,"lhotelCode is null");
        L2RAssert.stringBlank(l2rNo,"l2rNo is null");
        memeberCardPayApiParamDto.setPasswordReal(new String(decoder.decode(password), "UTF-8"));

        ReservationNmsStaInsideParamDto reservationNmsStaParam = new ReservationNmsStaInsideParamDto();
        reservationNmsStaParam.setLhotelGroupCode(lhotelGroupCode);
        reservationNmsStaParam.setLhotelCode(lhotelCode);
        reservationNmsStaParam.setL2RNo(l2rNo);
        reservationNmsStaParam.setOperType(ReservationConstant.OPERTYPE.CREATE);
        reservationNmsStaParam.setItem("CardPay");

        MemberCardPayDto memberCardPayDto = this.memberCardPay(memeberCardPayApiParamDto);
        reservationNmsStaParam.setOperSta("O");
        mnsUtil.putMessageToQueue(JetfireMnsConstant.QUEUE_ORDER_STA, JacksonUtil.beanToJson(reservationNmsStaParam));
        ReservationPayInsideParamDto param=new ReservationPayInsideParamDto();
        param.setLhotelCode(lhotelCode);
        param.setOrderNo(l2rNo);
        param.setAmount(memberCardPayDto.getAmount());
        param.setIsSavePmsPay(DefaultValue.F);
        param.setPayChannel("PMS");
        param.setTaNo(memberCardPayDto.getTaNo());
        param.setPayType("card_pay");
        reservationsFeignService.payment(param);
    }

}
